use axum::{Json, http::HeaderMap, extract::{Path, Query}};
use com::{ auth::claims::get_id, chrono::{expire_year_date, expire_year_exp_date}, code, encrypt, query, sea_orm::{connect, crud, fun::time_col_expr, send_paging, send_sql_ok} };
use sea_orm::{ entity::*, query::* };
use model::user::{ ActiveModel, Column, Entity };

pub async fn list(header: HeaderMap, Query(param): Query<JsonValue>) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let selector = Entity::find()
    .select_only()
    .columns([
        Column::Id, Column::Name,Column::Phone, Column::Role, Column::Mark, Column::Username,
        Column::Disabled, Column::ExpireTime
    ])
    // .expr_as_(get_url(Column::Head), "head")
    .expr_as_(time_col_expr(Column::CreateTime, 1), "create_time")
    // .expr_as_(date_format(Column::UpdateTime, 1), "update_time")
    .apply_if(query::str_op(&param,"name")?,  | q, v| q.filter(Column::Name.contains(v)) )
    .apply_if(query::i64_op(&param,"id")?, | q, v| q.filter(Column::Id.eq(v)) )
    .apply_if(query::str_op(&param,"phone")?, | q, v| q.filter(Column::Phone.starts_with(v)) )
    .apply_if(query::str_op(&param,"type")?, | q, v| q.filter(Column::Type.eq(v)) )
    .apply_if(query::i64_op(&param,"disabled")?, | q, v| q.filter(Column::Disabled.eq(v)) )
    .filter(Column::Id.ne(1))
    .filter(Column::CreateUser.eq(get_id(header)?))
    .order_by_asc(Column::Id);
    send_paging( selector, param).await
}
pub async fn save( headers: HeaderMap, Json(body):Json<JsonValue> ) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let id = query::i32_op(&body, "id")?;
    let user = get_id(headers)?;
    let mut model = ActiveModel{
        id              : id.map_or(NotSet, |v| Set(v) ),
        // username        : Set( query::str(&body, "username")? ),
        name            : Set( query::str_op(&body, "name")? ), 
        phone           : Set( query::str(&body, "phone")? ),
        password        : Set( encrypt::md5::encode(query::str(&body, "password")?) ),
        disabled        : Set( query::i8(&body, "disabled")? ),
        r#type          : Set( query::i32_op(&body, "type")? ),
        role            : Set( query::i8(&body, "role").unwrap_or(9) ),
        perm            : Set( query::json_op(&body, "perm")? ),
        mark            : Set( query::str_op(&body, "mark")? ),
        create_user     : Set( user.to_owned() ),
        ..Default::default()
    };
    if let Some(f) = id {
        if f.eq(&1) { return code::err("系统数据不允许操作"); }
        model.id = Set(f);
        model.update_user = Set( Some(user) );
        model.create_user = NotSet;
        model.username = NotSet;
    }else{
        model.id = NotSet;
        model.username = Set( query::str(&body, "username")? );
        let year = query::i64(&body, "year")?;
        model.expire_time = Set( Some( expire_year_date(year) ) )
    }
    let result = model.save(&conn).await;
    send_sql_ok(&conn, result).await
}
// 延期
pub async fn renewal( headers: HeaderMap, Json(body):Json<JsonValue> ) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let user = get_id(headers)?;
    let id = query::i32(&body, "id")?;
    let year = query::i64(&body, "year")?;
    let selector = Entity::find_by_id(id)
    .select_only()
    .column(Column::ExpireTime)
    .into_json().one(&conn).await;

    match selector {
        Ok( f ) => {
            let exp = if let Some(t) = f {
                expire_year_exp_date(year,query::date(&t, "expire_time")?)
            }else {
                expire_year_date(year)
            };
            let model = ActiveModel{
                id              : Set(id),
                expire_time     : Set( Some( exp ) ), 
                update_user     : Set( Some(user) ),
                ..Default::default()
            };
            code::send_ok( model.update(&conn).await )
        },
        Err(e) => code::sys(e.to_string())
    }
    
}
pub async fn find(Path( id ): Path<i32>) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let result = Entity::find_by_id(id)
    .select_only()
    .columns([
        Column::Id, Column::Name,Column::Phone, Column::Type, Column::Perm, Column::Username,
        Column::Disabled, Column::Mark, 
    ])
    // .expr_as_(get_url(Column::Head), "head")
    .into_model()
    .one(&conn).await;
    code::send_op_obj( result )
}
// pub async fn del(Path( id ): Path<String>) -> Result<Json<JsonValue>, Json<JsonValue>>{ crud::del::many(id, Entity, Column::Id).await }
pub async fn disabled( header: HeaderMap,Json(body):Json<JsonValue>) -> Result<Json<JsonValue>, Json<JsonValue>>{crud::bool::disabled::by_ids(header, Entity, &body).await}
// 修改密码
pub async fn mod_pwd( headers: HeaderMap, Json(body):Json<JsonValue> ) -> Result<Json<JsonValue>, Json<JsonValue>>{
    let conn = connect().await?;
    let id = get_id(headers)?;
    let old_pwd = query::str(&body, "old_pwd")?;
    let confirm_pwd = query::str(&body, "confirm_pwd")?;
    let password = query::str(&body, "password")?;
    if confirm_pwd != password { return code::err("两次密码不输入不一致") };

    let selector = Entity::find_by_id(id)
    .select_only()
    .column(Column::Password).into_json().one(&conn).await;

    match selector {
        Ok(f) => {
            if let Some(v) = f {
                let old = query::str(&v, "password")?;
                if encrypt::md5::encode(old_pwd) != old {
                    return code::err("旧密码错误")
                }
                let model = ActiveModel{
                    id              : Set(id),
                    password        : Set( encrypt::md5::encode(password) ),
                    ..Default::default()
                };
                let result = model.update(&conn).await;
                send_sql_ok(&conn, result).await
            }else{
                code::err("用户不存在")
            }
        },
        Err(e) => code::sys(e.to_string())
    }
    
}